﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.IO;

namespace Buffered_Response
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together.
    public class ServiceImpl : IStreamingService
    {
        private const int BLOCKSIZE = 65535;
        private const string FILEPATH = @"C:\temp\WCFSeries_01\Server\";

        public Stream GetData(string FileName)
        {
            return OpenStream(FileName);
        }

        private Stream OpenStream(string FileName)
        {
            Stream DataStream = null;

            try
            {
                switch (FileName.ToUpper())
                {

                    case "CRAY2":
                        DataStream = new FileStream(FILEPATH + "Cray2.jpg", FileMode.Open, FileAccess.Read);
                        break;
                    case "EARTH":
                        DataStream = new FileStream(FILEPATH + "Earth.jpg", FileMode.Open, FileAccess.Read);
                        break;
                    case "HELIX":
                        DataStream = new FileStream(FILEPATH + "Helix.tiff", FileMode.Open, FileAccess.Read);
                        break;
                    default:
                    case "DRYDEN":
                        DataStream = new FileStream(FILEPATH + "Dryden.jpg", FileMode.Open, FileAccess.Read);
                        break;
                }
            }
            catch (IOException ioExcept)
            {
                throw new FaultException<IOException>(ioExcept, "Unable to open/locate file: " + FILEPATH + FileName);
            }

            return DataStream;
        }   // OpenStream


        public ChunkedDataResult GetDataChunk(string FileName, int Offset)
        {
            ChunkedDataResult Result = new ChunkedDataResult();
            byte[] ReturnBuffer;

            using (Stream FileContents = OpenStream(FileName))
            {
                if (FileContents != null)
                {
                    Result.StreamSize = FileContents.Length;
                    int ReadSize = BLOCKSIZE;

                    // On the last call; only return an array of the required size instead of
                    //  a byte array with numerous empty elements...otherwise, allocate
                    //  an array the size of our block we've selected
                    if ((Offset + BLOCKSIZE) >= FileContents.Length)
                    {
                        ReturnBuffer = new byte[FileContents.Length - Offset];
                        ReadSize = (int)(FileContents.Length - Offset);
                    }
                    else
                        ReturnBuffer = new byte[BLOCKSIZE];

                    // If the requested offset is within the range of the file, 
                    // Then read that block and return it
                    if (Offset < FileContents.Length)
                    {
                        FileContents.Seek(Offset, SeekOrigin.Begin);
                        FileContents.Read(ReturnBuffer, 0, ReadSize);
                        Result.ChunkedBlock = ReturnBuffer;
                    }
                    else
                        Result.ChunkedBlock = null;
                }
            }

            return Result;

        }   // GetDataChunk
    }
}
